from base import *
from sqlalchemy.orm import relationship, backref
from sqlalchemy import Sequence
from aps.models.usuario import *
from aps.models.proyectorol import *
from aps.models.proyectousuario import *
from aps.models.proyectousuariorol import *
from aps.models.item import *
from aps.models.historial import *
from aps.models import *

class Proyecto(Base):
    """
    Clase que crea la tabla Proyecto 
    """
    __tablename__    = 'proyecto'
    id               = Column(Integer, Sequence('proyecto_id_seq'), primary_key=True)
    nombre           = Column(Text, nullable=False, unique=True)
    descripcion      = Column(Text)
    fechainicio      = Column(Date, nullable=False)
    fechafin         = Column(Date, nullable=False)
    estado           = Column(Text, nullable=False)
    nfases           = Column(Integer)
    complejidadtotal = Column(Integer)
    observaciones    = Column(Text)
    usuarios         = relationship("ProyectoUsuario", backref="proyecto")
    usuarios_x_rol   = relationship("ProyectoUsuarioRol")
    fases            = relationship("ProyectoFase", backref="proyecto")
    roles            = relationship("ProyectoRol", backref="proyecto")
    
    def __init__(self, nombre, descripcion, fechainicio, fechafin, estado, nfases, complejidadtotal, observaciones):
        """
        Metodo de instancia constructor que inicializa los parametros del objeto proyecto
        @type self: proyecto
        @param self: referencia al objeto que llama el metodo en este caso proyecto.
        @type nombre: Text
        @param nombre: campo que almacenara el nombre del proyecto.
        @type descripcion: Text
        @param descripcion: campo que almacenara la descripcion del proyecto.
        @type fechainicio: Date
        @param fechainicio: campo que almacenara la fecha de inicio del proyecto.
        @type fechafin: Text
        @param fechafin: campo que almacenara la fecha de fin del proyecto.
        @type estado: Text
        @param estado: campo que almacenara el estado del proyecto.
        @type nfases: Integer
        @param nfases: campo que almacenara la cantidad de fases del proyecto.
        @type complejidadtotal: Integer
        @param complejidadtotal: campo que almacenara la complejidadtotal del proyecto.
        @type observaciones: Text
        @param observaciones: campo que almacenara observaciones sobre el proyecto.
        """
        self.nombre = nombre
        self.descripcion = descripcion
        self.fechainicio = fechainicio
        self.fechafin = fechafin
        self.estado = estado
        self.observaciones = observaciones
        self.nfases = nfases
        self.complejidadtotal = complejidadtotal

    def eliminar_dependencias(self):
        """
        Metodo de instancia que elimina todas los relaciones de un registro de la tabla Proyectos
        para que pueda ser eliminado.
        @type self: proyecto
        @param self: referencia al objeto que llama el metodo en este caso proyecto.
        """
        ##buscar historial y eliminar
        bdsession.query(Historial).filter_by(idproyecto=self.id).delete()
        
        # En tabla proyectofase
        for f in self.fases:
            bdsession.delete(f)
        # En tabla proyectousuario
        for u in self.usuarios:
            bdsession.delete(u)
        # En tabla proyectorol
        for r in self.roles:
            bdsession.delete(r)
        # En tabla proyectousuariorol
        for ur in self.usuarios_x_rol:
            bdsession.delete(ur)
    
    def get_info(self):
        """
        Metodo que retorna informacion util para la generacion de informes.
        @type self: proyecto
        @param self: referencia al objeto que llama el metodo en este caso proyecto.
        """
        info      = {}
        proyecto  = self
        # DATOS DEL PROYECTO
        pnombre   = proyecto.nombre
        pfechai   = str(proyecto.fechainicio)
        pfechaf   = str(proyecto.fechafin)
        pliderid  = bdsession.query(ProyectoUsuarioRol).filter_by(idproyecto=proyecto.id,idrol=2).first()
        plider    = bdsession.query(Usuario).filter_by(id=pliderid.idusuario).first()
        plider    = str(plider.apellidos) + ',' + str(plider.nombres)
        pnmiebros = len(proyecto.usuarios)
        info['proyecto'] = [pnombre,pfechai,pfechaf,plider,pnmiebros]
        
        # MIEMBROS DEL PROYECTO
        pmiembros = [['Nombres', 'Apellidos', 'Nick', 'Fecha de nacimiento', 'E-mail']]
        for pu in proyecto.usuarios:
            unombres   = pu.usuario.nombres
            uapellidos = pu.usuario.apellidos
            unick      = pu.usuario.nick
            ufechanac  = str(pu.usuario.fechanac)
            uemail     = pu.usuario.email
            pmiembros.append([unombres,uapellidos,unick,ufechanac,uemail])
        info['miembros'] = pmiembros
        
        # ROLES DEL PROYECTO
        proles = [['Nombre','Descripcion','Numero de permisos']]
        for pr in proyecto.roles:
            rnombre = pr.rol.nombre
            rdesc   = pr.rol.descripcion
            rnperms = len(pr.rol.permisos)
            proles.append([rnombre,rdesc,rnperms])
        info['roles'] = proles
        
        # FASES DEL PROYECTO
        pfases = [['Nombre','Fecha Inicio','Fecha Fin','Estado','Orden']]
        for pf in proyecto.fases:
            fnombre = pf.fase.nombre
            ffechai = str(pf.fase.fechainicio)
            ffechaf = str(pf.fase.fechafin)
            festado = pf.fase.estado
            forden  = pf.orden
            pfases.append([fnombre,ffechai,ffechaf,festado,forden])
        info['fases'] = pfases
        
        # DETALLES POR FASE
        pfasen = []
        for pf in proyecto.fases:
            # DATOS DE LA FASE
            fase = pf.fase
            fnombre  = fase.nombre
            froles   = fase.roles
            fnroles  = len(froles)
            fitems   = bdsession.query(Item).filter_by(idfase=fase.id).all()
            fnitems  = len(fitems)
            fnlineas = len([x for x in fitems if x.idlineabase is not None])
            finfo = [fnombre,fnroles,fnitems,fnlineas]
            
            # ITEMS DE LA FASE
            fiinfo = [['Numeracion','Nombre','Version','Estado','Complejidad']]
            for item in fitems:
                finum     = item.numfase
                finombre  = item.nombre
                fiversion = item.version
                fiestado  = item.estado
                ficomplx  = item.complejidad
                fiinfo.append([finum,finombre,fiversion,fiestado,ficomplx])
            
            # ROLES DE LA FASE
            frolesh = [['Nombre','Descripcion','Numero de permisos']]
            for fr in froles:
                rnombre = fr.rol.nombre
                rdesc   = fr.rol.descripcion
                rnperms = len(fr.rol.permisos)
                frolesh.append([rnombre,rdesc,rnperms])
            
            # TIPOS DE ITEM DE LA FASE
            ftipos = [['Nombre','Prefijo','Descripcion','Cantidad de atributos']]
            for fti in fase.tipoitems:
                ftinombre  = fti.fase.nombre
                ftiprefijo = fti.tipoitem.prefijo
                ftidesc    = fti.tipoitem.descripcion
                ftinattr   = len(fti.tipoitem.atributos)
                ftipos.append([ftinombre,ftiprefijo,ftidesc,ftinattr])
            
            pfasen.append([finfo,fiinfo,frolesh,ftipos])
        info['fase_x'] = pfasen
    
        return info
